package com.pap.gateway.config.security.core;

import com.auth0.jwt.exceptions.SignatureGenerationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.pap.base.constant.JWTConstants;
import com.pap.base.dto.jwt.JWTUserDTO;
import com.pap.base.util.jwt.JWTTokenUtilss;
import com.pap.gateway.config.security.core.exception.*;
import com.pap.obj.vo.utils.collection.CollectionUtilss;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.Collection;
import java.util.stream.Collectors;

public class PapAuthenticationManager implements ReactiveAuthenticationManager {

    private static Logger logger  =  LoggerFactory.getLogger(PapAuthenticationManager.class);

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        if (authentication instanceof UsernamePasswordAuthenticationToken) {
            try {
                String jwtToken = authentication.getPrincipal().toString();
                JWTUserDTO jwtUserDTO = JWTTokenUtilss.parse(jwtToken, JWTConstants.SECRET);

                Collection<? extends GrantedAuthority> authorities =
                        Arrays.stream(CollectionUtilss.join(jwtUserDTO.getPermissionCodeList(), ",").split(","))
                                .map(SimpleGrantedAuthority::new)
                                .collect(Collectors.toList());

                Authentication authenticationReturn = new UsernamePasswordAuthenticationToken(
                        jwtUserDTO.getUserId(),
                        null,
                        authorities.stream().map(role -> new SimpleGrantedAuthority(((GrantedAuthority) role).getAuthority())).collect(Collectors.toList()));


                return Mono.just(authenticationReturn);
            } catch (TokenExpiredException e) {
                logger.error("PapAuthenticationManager.authenticate.ExpiredJwtException: [{}]", e.getMessage());
                return Mono.error(new PapExpiredJwtException(""));
            } catch (SignatureGenerationException e) {
                logger.error("PapAuthenticationManager.authenticate.SignatureException: [{}]", e.getMessage());
                return Mono.error(new PapSignatureException(""));
            } catch (IllegalArgumentException e) {
                logger.error("PapAuthenticationManager.authenticate.IllegalArgumentException: [{}]", e.getMessage());
                return Mono.error(new PapIllegalArgumentException(""));
            } catch (Exception e) {
                logger.error("PapAuthenticationManager.authenticate.IllegalArgumentException: [{}]", e.getMessage());
                return Mono.error(new PapIllegalArgumentException(""));
            }
        } else {
            return Mono.empty();
        }

    }
}